---
title: Astro 컨테이너 API (실험적)
sidebar:
  label: 컨테이너 API (실험적)
i18nReady: true
---
import Since from '~/components/Since.astro'

<p><Since v="4.9.0" /></p>

컨테이너 API를 사용하면 Astro 컴포넌트를 독립적으로 렌더링할 수 있습니다.

이 실험적인 서버 측 API는 다양한 잠재적 미래 활용 가능성을 열어주지만, 현재는 `vitest`와 같은 `vite` 환경에서 [`.astro` 컴포넌트 출력을 테스트](/ko/guides/testing/#vitest-및-컨테이너-api)할 수 있도록 범위가 제한되어 있습니다.

또한 요청 시 렌더링되는 페이지나 `vite` 외부(예: PHP 또는 Elixir 애플리케이션 내부)의 기타 "셸" 환경에서 컨테이너를 생성하기 위한 [렌더링 스크립트를 수동으로 직접 로드](#렌더러-직접-추가하기)할 수 있습니다.

이 API를 사용하면 [새 컨테이너를 생성](#create)하고, [문자열](#rendertostring) 또는 [`Response`](#rendertoresponse)를 반환하는 Astro 컴포넌트를 렌더링할 수 있습니다.

이 API는 실험적이며, [마이너 또는 패치 릴리스](/ko/upgrade-astro/#의미론적-버전-관리)에서도 호환성을 깨뜨리는 변경 사항이 발생할 수 있습니다. 변경 사항은 [Astro 변경 로그](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)를 참조하세요. 이 페이지는 항상 최신 버전의 Astro에 대한 정보로 업데이트됩니다.

## `create()`

<p>

**타입:** `(options?: AstroContainerOptions) => Promise<experimental_AstroContainer>`
</p>

컨테이너의 새 인스턴스를 생성합니다.

```js
import { experimental_AstroContainer } from "astro/container";

const container = await experimental_AstroContainer.create();
```

다음 옵션을 가진 객체를 받습니다.

```ts
export type AstroContainerOptions = {
	streaming?: boolean;
	renderers?: AddServerRenderer[];
};

export type AddServerRenderer =
	| {
			renderer: NamedSSRLoadedRendererValue;
			name: never;
	  }
	| {
			renderer: SSRLoadedRendererValue;
			name: string;
	  };
```

### `streaming` 옵션

<p>

**타입:** `boolean`<br />
**기본값:** `false`
</p>

[HTML 스트리밍](/ko/guides/on-demand-rendering/#html-스트리밍)을 사용한 컴포넌트 렌더링을 활성화합니다.

### `renderers` 옵션

<p>

**타입:** `AddServerRenderer[]`<br />
**기본값:** `[]`
</p>

컴포넌트에 필요한 로드된 클라이언트 렌더러 목록입니다. `.astro` 컴포넌트가 공식 Astro 통합(예: React, Vue 등)을 사용하여 [UI 프레임워크 컴포넌트](/ko/guides/framework-components/) 또는 MDX를 렌더링하는 경우에 이를 사용하세요.

정적 애플리케이션이나 런타임 시 컨테이너가 호출되지 않는 경우(예: `vitest`를 사용하여 테스트하는 경우)에는 컨테이너 API를 통해 렌더러를 자동으로 추가할 수 있습니다.

[요청 시 렌더링되는 애플리케이션](/ko/guides/on-demand-rendering/)이나 런타임 시 또는 다른 "셸"(예: PHP, Ruby, Java 등)에서 컨테이너가 호출되는 경우, 렌더러를 수동으로 직접 가져와야 합니다.

#### 컨테이너 API를 통해 렌더러 추가하기

각각의 공식 Astro 통합에 대해 `getContainerRenderer()` 도우미 함수를 가져와 사용하면 해당 클라이언트 및 서버 렌더링 스크립트를 노출할 수 있습니다. 이 함수는 `@astrojs/react`, `@astrojs/preact`, `@astrojs/solid-js`, `@astrojs/svelte`, `@astrojs/vue`, `@astrojs/mdx`에서 사용할 수 있습니다.

`@astrojs` npm 조직 외부의 렌더러 패키지의 경우, 해당 문서에서 `getContainerRenderer()` 또는 유사한 함수가 제공되는지 확인하세요.

`vite` (`vitest`, Astro 통합 등)를 사용할 때, 렌더러는 가상 모듈 `astro:container`의 `loadRenderers()` 함수를 통해 로드됩니다.

:::caution
`vite` 외부 또는 요청을 통해 사용하기 위해서는 [렌더러를 수동으로 직접 로드](#렌더러-직접-추가하기)해야 합니다.
:::

다음은 React 컴포넌트와 Svelte 컴포넌트를 렌더링하는 Astro 컴포넌트를 렌더링하는 데 필요한 객체를 제공하는 예시입니다.

```js
import { getContainerRenderer as reactContainerRenderer } from "@astrojs/react";
import { getContainerRenderer as svelteContainerRenderer } from "@astrojs/svelte";
import { loadRenderers } from "astro:container";

const renderers = await loadRenderers([reactContainerRenderer(), svelteContainerRenderer()]);
const container = await experimental_AstroContainer.create({
    renderers
})
const result = await container.renderToString(ReactWrapper);
```

#### 렌더러 직접 추가하기

컨테이너가 런타임 시 또는 다른 "셸"에서 호출될 때는 `astro:container` 가상 모듈의 도우미 함수를 사용할 수 없습니다. 필요한 서버 및 클라이언트 렌더러를 수동으로 직접 가져와 `addServerRenderer` 및 `addClientRenderer`를 사용하여 컨테이너에 저장해야 합니다.

프로젝트 빌드에는 서버 렌더러가 필요하며, 사용된 모든 프레임워크별로 컨테이너에 저장되어야 합니다. [`client:*` 지시어](/ko/reference/directives-reference/#클라이언트-지시어)를 사용하여 클라이언트 측 컴포넌트를 하이드레이션하려면 클라이언트 렌더러가 추가로 필요합니다.

프레임워크당 하나의 가져오기 구문이 필요합니다. 렌더러를 가져오면 서버 렌더러와 클라이언트 렌더러 모두 컨테이너에서 사용할 수 있게 됩니다. 그러나 **반드시 클라이언트 렌더러보다 서버 렌더러를 컨테이너에 먼저 추가해야 합니다.** 이렇게 하면 전체 컨테이너가 먼저 렌더링된 후 상호작용 가능한 컴포넌트를 하이드레이션할 수 있습니다.

다음은 정적 Vue 컴포넌트와 `.mdx` 페이지를 표시하기 위해 필요한 서버 렌더러를 수동으로 직접 가져오는 예시입니다. 또한 상호작용 가능한 React 컴포넌트를 위해 서버 및 클라이언트 렌더러를 모두 추가합니다.

```js
import reactRenderer from "@astrojs/react/server.js";
import vueRenderer from "@astrojs/vue/server.js";
import mdxRenderer from "@astrojs/mdx/server.js";

const container = await experimental_AstroContainer.create();
container.addServerRenderer({ renderer: vueRenderer });
container.addServerRenderer({ renderer: mdxRenderer });

container.addServerRenderer({ renderer: reactRenderer });
container.addClientRenderer({ name: "@astrojs/react", entrypoint: "@astrojs/react/client.js" });
```

## `renderToString()`

<p>

**타입:** <code>(component: AstroComponentFactory; options?: <a href="#렌더링-옵션">ContainerRenderOptions</a>) => Promise&lt;string&gt;</code>
</p>

이 함수는 컨테이너에서 특정 컴포넌트를 렌더링합니다. Astro 컴포넌트를 인수로 받아들이며, Astro 컴포넌트가 렌더링한 HTML/콘텐츠를 나타내는 문자열을 반환합니다.

```js
import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";

const container = await experimental_AstroContainer.create();
const result = await container.renderToString(Card);
```

이 함수는 내부적으로 [`renderToResponse()`](#rendertoresponse)와 `Response.text()`를 호출합니다.

또한 두 번째 인자로 [여러 옵션](#렌더링-옵션)을 포함할 수 있는 객체를 받습니다.

## `renderToResponse()`

<p>

**타입:** <code>(component: AstroComponentFactory; options?: <a href="#렌더링-옵션">ContainerRenderOptions</a>) => Promise&lt;Response&gt;</code>
</p>

컴포넌트를 렌더링하고, `Response` 객체를 반환합니다.

```js
import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";

const container = await experimental_AstroContainer.create();
const result = await container.renderToResponse(Card);
```

또한 두 번째 인자로 [여러 옵션](#렌더링-옵션)을 포함할 수 있는 객체를 받습니다.

## 렌더링 옵션

[`renderToResponse()`](#rendertoresponse)와 [`renderToString()`](#rendertostring) 모두 두 번째 인자로 객체를 받습니다.

```ts
export type ContainerRenderOptions = {
	slots?: Record<string, any>;
	props?: Record<string, unknown>;
	request?: Request;
	params?: Record<string, string | undefined>;
	locals?: App.Locals;
	routeType?: RouteType;
	partial?: boolean;
};
```

이러한 선택적 값들은 Astro 컴포넌트를 올바르게 렌더링하는 데 필요한 추가 정보를 제공하기 위해 렌더링 함수에 전달될 수 있습니다.

### `slots`

<p>

**타입**: `Record<string, any>`
</p>

[`<slots>`](/ko/basics/astro-components/#슬롯)로 렌더링할 콘텐츠를 전달하는 옵션입니다.

Astro 컴포넌트가 하나의 기본 슬롯을 렌더링하는 경우, `default`를 키로 사용하는 객체를 전달하세요.

```js name="Card.test.js"
import Card from "../src/components/Card.astro";

const result = await container.renderToString(Card, { 
  slots: { default: "어떤 값" }
});
```

컴포넌트가 명명된 슬롯을 렌더링하는 경우, 슬롯 이름을 객체 키로 사용하세요.

```astro name="Card.astro"
---
---
<div>
  <slot name="header" />
  <slot name="footer" />
</div>
```

```js name="Card.test.js"
import Card from "../src/components/Card.astro";

const result = await container.renderToString(Card, { 
  slots: {
    header: "Header content",
    footer: "Footer"
  }
});
```

컴포넌트를 계단식으로 렌더링할 수도 있습니다.

```astro name="Card.astro"
---
---
<div>
  <slot name="header" />
  <slot name="footer" />
</div>
```

```js name="Card.test.js"
import Card from "../src/components/Card.astro";
import CardHeader from "../src/components/CardHeader.astro";
import CardFooter from "../src/components/CardFooter.astro";

const result = await container.renderToString(Card, { 
  slots: { 
    header: await container.renderToString(CardHeader), 
    footer:  await container.renderToString(CardFooter)
  }
});
```

### `props` 옵션

<p>

**타입**: `Record<string, unknown>`
</p>

Astro 컴포넌트에 [속성](/ko/basics/astro-components/#컴포넌트-props)을 전달하는 옵션입니다.

```js name="Card.test.js"
import Card from "../src/components/Card.astro";

const result = await container.renderToString(Card, { 
  props: { name: "환영합니다!" }
});
```

```astro name="Card.astro"
---
// TypeScript 지원을 위해 사용합니다.
interface Props {
  name: string;
};

const { name } = Astro.props;
---
<div>
  {name}
</div>
```

### `request` 옵션

<p>

**타입**: `Request`
</p>

컴포넌트가 렌더링할 경로/URL에 대한 정보를 포함하는 `Request`를 전달하는 옵션입니다.

컴포넌트에서 `Astro.url` 또는 `Astro.request`와 같은 정보를 읽어야 할 때 이 옵션을 사용합니다.

가능한 헤더나 쿠키도 주입할 수 있습니다.

```js file="Card.test.js"
import Card from "../src/components/Card.astro";

const result = await container.renderToString(Card, { 
  request: new Request("https://example.com/blog", {
    headers: {
      "x-some-secret-header": "test-value"
    }
  })
});
```

### `params` 옵션

<p>

**타입**: `Record<string, string | undefined>`
</p>

[동적 라우트를 생성하는](/ko/guides/routing/#동적-라우트) Astro 컴포넌트에 경로 매개변수 정보를 전달하기 위한 객체입니다.

컴포넌트가 단일 라우트를 동적으로 생성하기 위해 `Astro.params` 값이 필요한 경우 이 옵션을 사용합니다.

```astro name="Card.astro"
---
const { locale, slug } = Astro.params;
---
<div></div>
```

```js file="LocaleSlug.test.js"
import LocaleSlug from "../src/components/[locale]/[slug].astro";

const result = await container.renderToString(LocaleSlug, { 
  params: {
    locale: "en",
    slug: "getting-started"
  }
});
```

### `locals` 옵션

<p>

**타입**: `App.Locals`
</p>

컴포넌트를 렌더링하기 위해 [`Astro.locals`](/ko/reference/api-reference/#locals)에 정보를 전달하는 옵션입니다.

로그인 상태와 같이 요청의 라이프사이클 동안 저장된 정보가 컴포넌트 렌더링에 필요한 경우 이 옵션을 사용합니다.

```astro name="Card.astro"
---
const { checkAuth } = Astro.locals;
const isAuthenticated = checkAuth();
---
{isAuthenticated ? <span>로그인 되었습니다.</span> : <span>로그인하세요.</span> }
```

```js file="Card.test.js"
import Card from "../src/components/Card.astro";

test("User is in", async () => {
  const result = await container.renderToString(Card, { 
    locals: {
      checkAuth() { return true; }
    }
  });
  
  // 결과에 "로그인 되었습니다."라는 문자열이 포함되어야 합니다.
});


test("User is out", async () => {
  const result = await container.renderToString(Card, { 
    locals: {
      checkAuth() { return false; }
    }
  });
  
  // 결과에 "로그인하세요."라는 문자열이 포함되어야 합니다.
});
```

### `routeType` 옵션

<p>

**타입**: `RouteType`
</p>

[엔드포인트](/ko/guides/endpoints/)를 렌더링하고 있다는 것을 명시하기 위해 `renderToResponse()`와 함께 사용할 수 있는 옵션입니다.

```js
container.renderToString(Endpoint, { routeType: "endpoint" });
```

```js file="endpoint.test.js"
import * as Endpoint from "../src/pages/api/endpoint.js";

const response = await container.renderToResponse(Endpoint, { 
  routeType: "endpoint"
});
const json = await response.json();
```

`POST`, `PATCH` 등 메서드에 대한 엔드포인트 테스트를 수행하려면 `request` 옵션을 사용하여 올바른 함수를 호출해야 합니다.

```js file="endpoint.js"
export function GET() {}

// 이 코드를 테스트해야 합니다.
export function POST() {}
```

```js file="endpoint.test.js" ins={5-7}
import * as Endpoint from "../src/pages/api/endpoint.js";

const response = await container.renderToResponse(Endpoint, { 
    routeType: "endpoint",
    request: new Request("https://example.com", {
      method: "POST" // 테스트를 위해 POST 메서드를 지정합니다.
    })
});
const json = await response.json();
```

### `partial` 옵션

<p>

**타입:** `boolean`<br />
**기본값:** `true`<br/>
<Since v="4.16.6" />
</p>

컨테이너 API가 컴포넌트를 [페이지 부분](/ko/basics/astro-pages/#페이지-부분-page-partials)처럼 렌더링할지 여부입니다. 이는 일반적으로 `components.boolean`을 렌더링할 때 원하는 동작이므로 전체 페이지 셸 없이도 컴포넌트를 렌더링할 수 있습니다.

`<!DOCTYPE html>`을 포함한 전체 Astro 페이지로 컴포넌트를 렌더링하려면 `partial`을 `false`로 설정하여 이 동작을 비활성화할 수 있습니다.

```js name="Card.test.js" ins={4}
import Blog from "../src/pages/Blog.astro";

const result = await container.renderToString(Card, {
    partial: false 
});
console.log(result) // HTML의 시작 부분에 `<!DOCTYPE html>`를 포함합니다.
```
